package com.hightrast.service.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.hightrast.service.api.baseEntity.exception.ServiceException;
import com.hightrast.service.api.domain.qo.rastRole.AddUserRoleQo;
import com.hightrast.service.api.domain.qo.rastUser.LoginQo;
import com.hightrast.service.api.domain.qo.rastUser.RegisterQo;
import com.hightrast.service.api.domain.qo.rastUser.UpdateForgotPasswordQo;
import com.hightrast.service.api.domain.vo.rastUser.LoginVo;
import com.hightrast.service.api.entity.RastRole;
import com.hightrast.service.api.entity.RastUser;
import com.hightrast.service.api.enums.AccountStatusEnum;
import com.hightrast.service.api.enums.RoleTypeEnum;
import com.hightrast.service.service.IRastRoleService;
import com.hightrast.service.service.IRastUserRoleAuthService;
import com.hightrast.service.service.IRastUserRoleService;
import com.hightrast.service.service.IRastUserService;
import com.hightrast.service.util.BaseEntityUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Objects;
import java.util.Optional;

/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author hx
 * @since 2025-01-11
 */
@Slf4j
@Service
public class RastUnAuthOpenServiceImpl {


    @Resource
    IRastUserService userService;
    @Resource
    IRastUserRoleAuthService userRoleAuthService;
    @Resource
    IRastUserRoleService userRoleService;
    @Resource
    IRastRoleService roleService;

    /**
     * 登陆
     *
     * @param qo
     * @return
     */
    public LoginVo login(LoginQo qo) {
        RastUser user = userService.getOne(new LambdaQueryWrapper<RastUser>()
                .eq(RastUser::getAccount, qo.getAccount()));
        Optional.ofNullable(user)
                // 账号不存在
                .orElseThrow(() -> new ServiceException("Account does not exist"));
        if (Objects.equals(user.getStatus(), AccountStatusEnum.DEACTIVATED.getValue())) {
            // 账号已停用
            throw new ServiceException("Account deactivated");
        }
        // 验证密码
        if (!BCrypt.checkpw(qo.getPassword(), user.getPassword())) {
            // 密码不正确
            throw new ServiceException("Incorrect password");
        }
        if(StpUtil.isLogin()){
            StpUtil.logout();
        }
        // soToken登陆
        StpUtil.login(user.getId(), new SaLoginModel()
                // 实现‘记住我’
                .setIsLastingCookie(qo.getRememberMe().equals(1)));
        StpUtil.getSession().set("user",JSON.toJSONString(user));

        LoginVo loginVo = BeanUtil.copyProperties(user, LoginVo.class);
        loginVo.setToken(StpUtil.getTokenValue());
        return loginVo;
    }

    /**
     * 注册
     *
     * @param qo
     */
    @Transactional
    public void register(RegisterQo qo) {
        // 验证账号是否重复
        RastUser user = userService.getOne(new LambdaQueryWrapper<RastUser>()
                .eq(RastUser::getAccount, qo.getAccount()));
        if (Objects.nonNull(user)) throw new ServiceException("This account already exists and cannot be recreated");
        RastUser rastUser = BeanUtil.copyProperties(qo, RastUser.class);
        // 加密密码
        rastUser.setPassword(BCrypt.hashpw(qo.getPassword()));
        BaseEntityUtil.save(rastUser,rastUser);
        userService.save(rastUser);
        log.info("新增用户: {} ", rastUser);
        // 创建一条授权用户角色通知
        RastUser saveUser = userService.getOne(new LambdaQueryWrapper<RastUser>()
                .eq(RastUser::getAccount, qo.getAccount()));
        RastRole role = Optional.ofNullable(roleService.getOne(new LambdaQueryWrapper<RastRole>()
                .eq(RastRole::getRoleType, RoleTypeEnum.DESIGNER.getValue())))
                // 授权角色不存在
                .orElseThrow(() -> new ServiceException("Authorization role does not exist"));
        // 新增用户角色关联数据
        AddUserRoleQo userRoleQo = new AddUserRoleQo();
        userRoleQo.setRoleId(role.getId());
        userRoleQo.setRoleName(role.getRoleName());
        userRoleQo.setUserId(saveUser.getId());
        userRoleQo.setUsername(saveUser.getUserName());
        userRoleService.saveUpdateUserRole(userRoleQo);

//        RastUserRoleAuth userRoleAuth = new RastUserRoleAuth();
//        userRoleAuth.setUserId(saveUser.getId());
//        userRoleAuth.setUserName(saveUser.getUserName());
//        userRoleAuthService.addUserRoleAuth(userRoleAuth);
    }

    /**
     * 重置密码
     * @param qo
     */
    public void forgotPassword(UpdateForgotPasswordQo qo) {

        // TODO  验证验证码是否相同

        // 验证账号是否存在
        RastUser user = userService.getOne(new LambdaQueryWrapper<RastUser>()
                .eq(RastUser::getAccount, qo.getAccount()));
        Optional.ofNullable(user)
                // 账号不存在
                .orElseThrow(() -> new ServiceException("Account does not exist"));
        // 加密密码
        user.setPassword(BCrypt.hashpw(qo.getPassword()));
        BaseEntityUtil.update(user,user);
        userService.updateById(user);
        log.info(">>>>> 用户修改密码 >>>>>");
    }
}
